import { Tabs, Steps, Callout } from "nextra/components";
import UniversalTabs from "../../components/UniversalTabs";

# Kubernetes Quickstart

## Prerequisites

- A Kubernetes cluster currently set as the current context in `kubectl`
- `kubectl` and `helm` installed

## Quickstart

<Steps>
### Get Hatchet Running

To deploy `hatchet-stack`, run the following commands:

```sh
helm repo add hatchet https://hatchet-dev.github.io/hatchet-charts
helm install hatchet-stack hatchet/hatchet-stack --set caddy.enabled=true
```

This default installation will run the Hatchet server as an internal service in the cluster and spins up a reverse proxy via `Caddy` to get local access. To view the Hatchet server, run the following command:

```sh
export NAMESPACE=default # TODO: replace with your namespace
export POD_NAME=$(kubectl get pods --namespace $NAMESPACE -l "app=caddy" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace $NAMESPACE $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace $NAMESPACE port-forward $POD_NAME 8080:$CONTAINER_PORT
```

And then navigate to `http://localhost:8080` to see the Hatchet frontend running. You can log into Hatchet with the following credentials:

```
Email: admin@example.com
Password: Admin123!!
```

### Port forward to the Hatchet engine

```sh
export NAMESPACE=default # TODO: replace with your namespace
export POD_NAME=$(kubectl get pods --namespace $NAMESPACE -l "app.kubernetes.io/name=engine" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace $NAMESPACE $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace $NAMESPACE port-forward $POD_NAME 7070:$CONTAINER_PORT
```

This will spin up the Hatchet engine service on `localhost:7070` which you can then connect to from the examples.

### Generate an API token

To generate an API token, navigate to the `Settings` tab in the Hatchet frontend and click on the `API Tokens` tab. Click the `Generate API Token` button to create a new token. Save this to a `.env` file in the root of your project.

```sh
cat <<EOF > .env
HATCHET_CLIENT_TOKEN="<your token here>"
HATCHET_CLIENT_TLS_STRATEGY=none
EOF
```

### Run your first worker

<UniversalTabs items={['Python', 'Typescript', 'Go']}>
  <Tabs.Tab>
Make sure you have the following dependencies installed:

```sh
pip install python-dotenv
pip install hatchet-sdk
```

We are using [`python-dotenv`](https://pypi.org/project/python-dotenv/) to load the environment variables from a `.env` file. This isn't required, and you can use your own method to load environment variables.

Create a `worker.py` file with the following contents:

```python filename="worker.py" copy
from hatchet_sdk import Hatchet
from dotenv import load_dotenv

load_dotenv()

hatchet = Hatchet(debug=True)

@hatchet.workflow(name="first-python-workflow",on_events=["user:create"])
class MyWorkflow:
    @hatchet.step()
    def step1(self, context):
        return {
            "result": "success"
        }

worker = hatchet.worker('first-worker')
worker.register_workflow(MyWorkflow())

worker.start()
```

Open a new terminal and start the worker with:

```sh
python3 worker.py
```

  </Tabs.Tab>
  <Tabs.Tab>
First, install `@hatchet-dev/typescript-sdk` via:

```sh npm2yarn
npm i @hatchet-dev/typescript-sdk
npm i dotenv
```

We also use `dotenv` to load the environment variables from a `.env` file. This isn't required, and you can use your own method to load environment variables.

Next, copy the following code into a `worker.ts` file:

```typescript filename="worker.ts" copy
import Hatchet, { Workflow } from "@hatchet-dev/typescript-sdk";
import dotenv from "dotenv";

dotenv.config();

const hatchet = Hatchet.init();

const workflow: Workflow = {
  id: "first-typescript-workflow",
  description: "This is my first workflow",
  on: {
    event: "user:create",
  },
  steps: [
    {
      name: "step1",
      run: async (ctx) => {
        console.log(
          "starting step1 with the following input",
          ctx.workflowInput(),
        );

        return {
          result: "success!",
        };
      },
    },
  ],
};

const worker = hatchet.worker("my-worker");
await worker.registerWorkflow(workflow);
worker.start();
```

Next, modify your `package.json` to include a script to start:

```json
{
  // ...rest of your `package.json`
  "scripts": {
    // ...existing scripts
    "worker": "npx ts-node worker.ts"
  }
}
```

Now to start the worker, in a new terminal run:

```sh npm2yarn
npm run worker
```

  </Tabs.Tab>
  <Tabs.Tab>
  In a new Go project, copy the following code into a `main.go` file:

```go filename="main.go" copy
package main

import (
	"fmt"

	"github.com/joho/godotenv"

	"github.com/hatchet-dev/hatchet/pkg/client"
	"github.com/hatchet-dev/hatchet/pkg/cmdutils"
	"github.com/hatchet-dev/hatchet/pkg/worker"
)

type stepOutput struct{}

func main() {
	err := godotenv.Load()
	if err != nil {
		panic(err)
	}

	c, err := client.New()

	if err != nil {
		panic(fmt.Sprintf("error creating client: %v", err))
	}

	w, err := worker.NewWorker(
		worker.WithClient(
			c,
		),
		worker.WithMaxRuns(1),
	)
	if err != nil {
		panic(fmt.Sprintf("error creating worker: %v", err))
	}

	err = w.RegisterWorkflow(
		&worker.WorkflowJob{
			Name:        "simple-workflow",
			Description: "Simple one-step workflow.",
      On:          worker.Events("simple"),
			Steps: []*worker.WorkflowStep{
				worker.Fn(func(ctx worker.HatchetContext) (result *stepOutput, err error) {
					fmt.Println("executed step 1")

					return &stepOutput{}, nil
				},
				).SetName("step-one"),
			},
		},
	)
	if err != nil {
		panic(fmt.Sprintf("error registering workflow: %v", err))
	}

	interruptCtx, cancel := cmdutils.InterruptContextFromChan(cmdutils.InterruptChan())
	defer cancel()

	cleanup, err := w.Start()
	if err != nil {
		panic(fmt.Sprintf("error starting worker: %v", err))
	}

	<-interruptCtx.Done()
	if err := cleanup(); err != nil {
		panic(err)
	}
}
```

Next, run the following command to start the worker:

```sh
go run main.go
```

</Tabs.Tab>
</UniversalTabs>

### Run your first workflow

The worker is now running and listening for steps to execute. You should see your first worker registered in the `Workers` tab of the Hatchet dashboard:

![Quickstart 1](/quickstart-1.png)

You can now trigger your first workflow by navigating to the `Workflows` tab, selecting your workflow, and clicking the top right "Trigger workflow" button:

![Quickstart 2](/quickstart-2.png)

That's it! You've successfully deployed Hatchet and run your first workflow.

</Steps>
